/*============================================================================
  File:      ParamHandler.h
 
  Summary:   This file contains macros and routines to handle all of the 
			 parameter passing in a plug-in algorithm. This functionality only 
			 works if you are using static member functions of the algorithm 
			 class to implement the IDMAlgorithmMetadata interface.
 
  Date:		 June 30, 2004
------------------------------------------------------------------------------
  This file is part of the Microsoft SQL Server Code Samples.
 
  Copyright (C) 2003 Microsoft Corporation.  All rights reserved.
 
This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.
 
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
============================================================================*/
#pragma once

// 

// The type strings for the parameters should be the same as the enumeration 
// names of DBTYPEENUM (oledb.h) for the scalar numeric types. We'll use the
// DBTYPEENUM to store these.

/*
DBTYPE_I2
DBTYPE_I4
DBTYPE_R4
DBTYPE_R8
DBTYPE_BOOL
DBTYPE_UI2
DBTYPE_UI4
DBTYPE_I8
DBTYPE_UI8
*/

#include "..\..\dmalgo.h"
#include "DmhMemory.h"
#include <oledb.h>	// For DBTYPEENUM

// Convert from the string name to the enumeration. 
DBTYPEENUM	Dbtypeenum(const WCHAR* szType);

// Convert from the enumeration to the string name
const WCHAR* SzType(DBTYPEENUM dbtypeenum);


#define MAX_DESCRIPTION_LENGTH 2000

// Structure to hold all of the information about a parameter
struct DMHPARAM
{
	// Constructor

	DMHPARAM(const WCHAR*	szName,
			 int			iIDStrDescription,	// Resource string ID
			 DBTYPEENUM		dbtypeenum,			// Parameter type
			 BOOL			bRequired,
			 BOOL			bExposed,
			 ULONG			ulFlags,
			 const WCHAR*	szDefault,			
			 const WCHAR*	szValueEnum)		// User-friendly description of the values [0,20)
	{
		_szName				= szName;
		_iIDStrDescription	= iIDStrDescription;
		_dbtypeenum			= dbtypeenum;
		_bRequired			= bRequired;
		_bExposed			= bExposed;
		_ulFlags			= ulFlags;
		_szDefault			= szDefault;
		_szValueEnum		= szValueEnum;
	}

	const WCHAR*	_szName;			
	int				_iIDStrDescription;
	DBTYPEENUM		_dbtypeenum;			
	BOOL			_bRequired;		
	BOOL			_bExposed;		
	ULONG			_ulFlags;		
	const WCHAR*	_szDefault;		
	const WCHAR*	_szValueEnum;
};

// Macros so that we can declare the algorithm parameters and have them all live
// on the stack

// The DECLARE_STATIC_PARAMETER_HANDLING() should be placed in the class declaration
// of the algorithm.

#define DECLARE_STATIC_PARAMETER_HANDLING()		\
	static DMHPARAM			_rgdmhparam[];		\
	static int				_cdmhparam;			\
	static DMHPARAMHANDLER	_dmhparamhandler;	

// The parameter-declaration list should be placed in the implementation file of the
// algorithm.

#define BEGIN_PARAMETER_DECLARATION(CLASS) \
	DMHPARAM		CLASS::_rgdmhparam[] = {

#define DECLARE_PARAMETER(szName,iIDStrDesc,szType,bReq,bExposed,ulFlags,szDefault,szValueEnum)	\
	DMHPARAM(szName,iIDStrDesc,szType,bReq,bExposed,ulFlags,szDefault,szValueEnum),

#define END_PARAMETER_DECLARATION(CLASS) \
		DMHPARAM(L"",-1,DBTYPE_EMPTY,false,false,0,L"",L"") /* Needed in case there's no parameters */ \
	}; \
	\
	/* Note that _cdmhparam is set to one less than the total: this is because we added	*/ \
	/* an extra empty parameter at the end of the static list.							*/ \
	int					CLASS::_cdmhparam = sizeof(CLASS::_rgdmhparam) / sizeof(DMHPARAM) - 1; \
	DMHPARAMHANDLER		CLASS::_dmhparamhandler(CLASS::_rgdmhparam, CLASS::_cdmhparam);
	

// The parameter-handing class. This class implements all of the static IDMAlgorithmMetadata
// parameter-handling functions in the algorithm. It also parses the values passed in calls
// to IDMAlgorithm::InsertCases()

class DMHPARAMHANDLER
{
  protected:

	DMHPARAM*	_rgdmhparam;
	UINT		_cdmhparam;

  public:

	DMHPARAMHANDLER(DMHPARAM* rgdmhparam, int cdmhparam)
	{
		_rgdmhparam	= rgdmhparam;
		_cdmhparam	= cdmhparam;
	}

	// Functions to extract the parameter values for simple types. You can
	// use these in IDMAlgorithm::InsertCases() to extract the values passed
	// in. These simple implementations traverse all of the parameters on 
	// each call. If szParameter is not included in the provided rgszParameter,
	// the list _rgdmhparam is traversed and the default value is returned. The
	// functions return E_FAIL if szParameter is not found.

	HRESULT GetParameterValue(IDMContextServices*	pidmcontextservices,
							  double&				dblValue,		// Output value
							  const WCHAR*			szParameter,	// Name of desired parameter
							  ULONG					cParameter,		
							  WCHAR**				rgszParameter,
							  DMVariantPtr  		rgdmvariantptrValue[]);

	HRESULT GetParameterValue(IDMContextServices*	pidmcontextservices,
							  LONG&					lValue,			// Output value
							  const WCHAR*			szParameter,	// Name of desired parameter
							  ULONG					cParameter,		
							  WCHAR**				rgszParameter,
							  DMVariantPtr  		rgdmvariantptrValue[]);

	HRESULT GetParameterValue(IDMContextServices*	pidmcontextservices,
							  bool&					bValue,			// Output value
							  const WCHAR*			szParameter,	// Name of desired parameter
							  ULONG					cParameter,		
							  WCHAR**				rgszParameter,
							  DMVariantPtr  		rgdmvariantptrValue[]);

	// Helper for the above: populate a VARIANT

	HRESULT	GetVariant(IDMContextServices*	pidmcontextservices,
							const WCHAR*	szParameter,	// Name of desired parameter
							VARIANT&		variant,
							ULONG			cParameter,		
							WCHAR**			rgszParameter,
							DMVariantPtr	rgdmvariantptrValue[]);



	// Helper function for creating strings

	HRESULT CreateDMString(IDMContextServices*	pidmcontextservices,
						   const WCHAR*			szToCopy,
						   DMString*			pdmstring);
						   
	// Parsing function that uses VARIANT and WCHAR* instead of a DMVariantPtr
	// and DMString

	HRESULT ParseParameterValue(ULONG					in_iParameter,
								const WCHAR*			in_szParameter,
								VARIANT&				out_variantParameter);

	// Copies of the IDMAlgorithmMetadata parameter-handing functions. 
	
	HRESULT	GetNumParameters(IDMContextServices* in_pContext, ULONG* pcParameter);

	HRESULT GetParameterName(IDMContextServices*	in_pContext,
							 ULONG					in_iParameter,
							 DMString				*io_pstrParameterName);

	HRESULT	GetParameterType(IDMContextServices*	in_pContext,
							 ULONG					in_iParameter,
							 DMString*				io_pstrParameterType);

	HRESULT GetParameterIsRequired(IDMContextServices*	in_pContext,
						  ULONG					in_iParameter,
						  BOOL*					out_pfIsRequired);

	HRESULT GetParameterIsExposed(IDMContextServices*	in_pContext, ULONG in_iParameter, BOOL* out_pfIsExposed);
	
	HRESULT GetParameterFlags(IDMContextServices* in_pContext,
							  ULONG in_iParameter,
							  ULONG *out_pulParameterFlags);
	
	HRESULT GetParameterDescription(IDMContextServices*	in_pContext,
									ULONG					in_iParameter,
									ULONG					in_LocaleID,
									DMString*				io_pstrDescription);

	HRESULT GetParameterDefaultValue(IDMContextServices*	in_pContext,
									 ULONG					in_iParameter,
									 DMString*				io_pstrDefaultValue);

	HRESULT GetParameterValueEnumeration(IDMContextServices*	in_pContext,
										 ULONG					in_iParameter,
										 DMString*				io_pstrValueEnumeration);

	HRESULT ParseParameterValue(IDMContextServices*	in_pContext,
								ULONG					in_iParameter,
								DMString*				in_pstrParameterStrValue,
								DMVariantPtr			io_pParameterMappedValue);
};